commonlibsse_ng\re\n/
NiSmartPointer.rs1use core::fmt;
2use std::cmp::Eq;
3use std::hash::{Hash, Hasher};
4use std::marker::PhantomData;
5use std::ptr::NonNull;
6
7pub trait RefCountable {
8 fn inc_ref_count(&self);
10 fn dec_ref_count(&mut self);
12}
13
14pub struct NiPointer<T: RefCountable> {
15 ptr: Option<NonNull<T>>,
16 _marker: PhantomData<T>,
17}
18
19impl<T: RefCountable> fmt::Debug for NiPointer<T> {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 f.debug_struct("NiPointer").field("ptr", &self.ptr).field("_marker", &self._marker).finish()
22 }
23}
24
25impl<T: RefCountable> Default for NiPointer<T> {
26 #[inline]
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl<T: RefCountable> NiPointer<T> {
33 #[inline]
34 pub const fn new() -> Self {
35 Self { ptr: None, _marker: PhantomData }
36 }
37
38 #[inline]
39 pub fn from_raw(ptr: *mut T) -> Self {
40 let ni_pointer = Self { ptr: NonNull::new(ptr), _marker: PhantomData };
41 ni_pointer.try_attach();
42 ni_pointer
43 }
44
45 fn try_attach(&self) {
46 if let Some(ref_ptr) = self.ptr {
47 unsafe { ref_ptr.as_ref().inc_ref_count() };
48 }
49 }
50
51 fn try_detach(&mut self) {
52 if let Some(mut ptr) = self.ptr.take() {
53 unsafe { ptr.as_mut().dec_ref_count() };
54 }
55 }
56
57 #[inline]
58 pub fn reset(&mut self) {
59 self.try_detach();
60 }
61
62 #[inline]
63 pub const fn is_null(&self) -> bool {
64 self.ptr.is_none()
65 }
66
67 #[inline]
68 pub const fn as_ptr(&self) -> Option<NonNull<T>> {
69 self.ptr
70 }
71
72 #[inline]
73 pub fn as_ref<'a>(&self) -> Option<&'a T> {
74 self.ptr.as_ref().map(|ptr| unsafe { ptr.as_ref() })
75 }
76
77 #[inline]
78 pub fn as_mut<'a>(&mut self) -> Option<&'a mut T> {
79 self.ptr.as_mut().map(|ptr| unsafe { ptr.as_mut() })
80 }
81}
82
83impl<T: RefCountable> Clone for NiPointer<T> {
84 #[inline]
85 fn clone(&self) -> Self {
86 let mut cloned = Self::new();
87 if let Some(ptr) = self.ptr {
88 cloned.ptr = Some(ptr);
89 cloned.try_attach();
90 }
91 cloned
92 }
93}
94
95impl<T: RefCountable> Drop for NiPointer<T> {
96 #[inline]
97 fn drop(&mut self) {
98 self.try_detach();
99 }
100}
101
102impl<T: RefCountable> PartialEq for NiPointer<T> {
103 #[inline]
104 fn eq(&self, other: &Self) -> bool {
105 self.ptr == other.ptr
106 }
107}
108
109impl<T: RefCountable> Eq for NiPointer<T> {}
110
111impl<T: RefCountable> Hash for NiPointer<T> {
112 #[inline]
113 fn hash<H: Hasher>(&self, state: &mut H) {
114 if let Some(ptr) = self.ptr {
115 ptr.as_ptr().hash(state);
116 }
117 }
118}
119
120impl<T: RefCountable> From<*mut T> for NiPointer<T> {
121 #[inline]
122 fn from(ptr: *mut T) -> Self {
123 Self::from_raw(ptr)
124 }
125}
126
127impl<T: RefCountable> From<Option<NonNull<T>>> for NiPointer<T> {
128 #[inline]
129 fn from(ptr: Option<NonNull<T>>) -> Self {
130 let ret = Self { ptr, _marker: PhantomData };
131 ret.try_attach();
132 ret
133 }
134}
135
136